package middleware

import (
	"buding-ai/internal/web/response"
	"context"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"runtime/debug"
)

// AppError 应用错误接口
type AppError interface {
	error
	// Code 返回错误码
	Code() int
	// Message 返回错误消息
	Message() string
}

// CustomError 自定义错误结构体
type CustomError struct {
	StatusCode int    // HTTP状态码
	ErrCode    int    // 业务错误码
	ErrMsg     string // 错误消息
}

// Error 实现error接口
func (e *CustomError) Error() string {
	return e.ErrMsg
}

// Code 实现AppError接口
func (e *CustomError) Code() int {
	return e.ErrCode
}

// Message 实现AppError接口
func (e *CustomError) Message() string {
	return e.ErrMsg
}

// NewAppError 创建应用错误
func NewAppError(code int, msg string) AppError {
	return &CustomError{
		StatusCode: 200,  // 默认HTTP状态码
		ErrCode:    code, // 业务错误码
		ErrMsg:     msg,  // 错误消息
	}
}

// ErrorHandler 全局错误处理中间件
func ErrorHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 捕获panic
		defer func() {
			if err := recover(); err != nil {
				// 获取堆栈信息
				stack := string(debug.Stack())

				// 记录错误日志
				middlewareLogger.Printf("系统内部错误: %v\n堆栈信息:\n%s", err, stack)

				// 根据err类型处理
				var appErr AppError
				switch e := err.(type) {
				case AppError:
					// 应用内部定义的错误
					appErr = e
				case *CustomError:
					// 自定义错误
					appErr = e
				case string:
					// 字符串错误
					appErr = NewAppError(response.CodeInternalError, e)
				case error:
					// 标准错误
					if errors.Is(e, context.DeadlineExceeded) {
						appErr = NewAppError(response.CodeServiceUnavailable, "请求超时")
					} else if errors.Is(e, context.Canceled) {
						appErr = NewAppError(response.CodeServiceUnavailable, "请求被取消")
					} else {
						appErr = NewAppError(response.CodeInternalError, e.Error())
					}
				default:
					// 未知类型错误
					appErr = NewAppError(response.CodeInternalError, fmt.Sprintf("系统内部未知错误: %v", err))
				}

				// 返回错误响应
				response.Fail(c, appErr.Code(), appErr.Message())

				// 终止后续中间件
				c.Abort()
			}
		}()

		// 继续处理请求
		c.Next()

		// 处理请求过程中产生的错误
		if len(c.Errors) > 0 {
			// 记录错误日志
			middlewareLogger.Printf("请求处理错误: %v", c.Errors)

			// 获取第一个错误
			err := c.Errors[0].Err

			// 根据错误类型处理
			var appErr AppError
			if e, ok := err.(AppError); ok {
				appErr = e
			} else {
				appErr = NewAppError(response.CodeInternalError, err.Error())
			}

			// 返回错误响应
			response.Fail(c, appErr.Code(), appErr.Message())

			// 终止后续中间件
			c.Abort()
		}
	}
}
